package gamelogic

import (
	"encoding/json"
	"server_cluster/common/config"
	"server_cluster/common/gdconf"
	"server_cluster/common/logger"
	"server_cluster/common/tools"
	"server_cluster/logic/db"
	"server_cluster/logic/sharemem"
	"strconv"
)

// LoadConfigData2Shm 更新共享内存中的配置表数据
func LoadConfigData2Shm() {
	buf, err := json.Marshal(gdconf.CONF.GameDataMaps)
	if err != nil {
		logger.Error("GameDataConfig Marshal Err:" + err.Error())
		return
	}
	copyLen := len(buf)
	if copyLen > sharemem.CONFIG_BUFFER_MAX {
		logger.Error("GameDataConfig Marshal Length over Limit curLen:" + strconv.Itoa(copyLen))
		return
	}
	copy(sharemem.MyShm.Cfg[:], buf[:copyLen])
	if copyLen < sharemem.CONFIG_BUFFER_MAX {
		clear(sharemem.MyShm.Cfg[copyLen:])
	}
	sharemem.MyShm.CfgLen = int32(copyLen)
}

func DM_user_role(shm_user *sharemem.User) int16 {
	var data []db.DbRole
	res := db.Conn.Where("uid = ?", shm_user.Id.NewVal).Find(&data)
	if res.Error != nil {
		return config.DBERROR
	}

	for k, v := range data {
		if k >= sharemem.ROLE_MAX {
			return config.OVERRUN
		}
		shm_user.Role[k].Id.NewVal = v.Id
		shm_user.Role[k].Id.OldVal = v.Id
		shm_user.Role[k].Level = v.Level
		shm_user.Role[k].Exp = v.Exp
		shm_user.Role[k].Promote = v.Promote
		shm_user.Role[k].Star = v.Star
		if v.UnlockTalent != "" {
			err := json.Unmarshal([]byte(v.UnlockTalent), &(shm_user.Role[k].TalentList))
			if err != nil {
				return config.JSONERROR
			}
		}
		shm_user.Role[k].CurrEnergy = v.CurrEnergy
		shm_user.Role[k].CurrHp = v.CurrHp
		if v.UnlockCaptainSkill != "" {
			err := json.Unmarshal([]byte(v.UnlockCaptainSkill), &(shm_user.Role[k].CaptainSkillList))
			if err != nil {
				return config.JSONERROR
			}
		}
	}

	return config.OK
}

func DM_user_item(shm_user *sharemem.User) int16 {
	var data []db.DbItem
	res := db.Conn.Where("uid = ?", shm_user.Id.NewVal).Find(&data)
	if res.Error != nil {
		return config.DBERROR
	}
	for _, v := range data {
		if v.Type == gdconf.ITEM_TYPE_SPECIAL {
			k := v.Cell
			if k >= sharemem.USER_ITEM_SPECIAL {
				return config.OVERRUN
			}
			shm_user.Item.Special[k].Id.NewVal = v.Id
			shm_user.Item.Special[k].Id.OldVal = v.Id
			shm_user.Item.Special[k].Type = v.Type
			shm_user.Item.Special[k].Num = v.Num
			shm_user.Item.Special[k].Day = v.Day
			if v.CdTime != nil {
				shm_user.Item.Special[k].CdEndTime = tools.Time2timestamp(*(v.CdTime))
			}
			if v.EndTime != nil {
				shm_user.Item.Special[k].EndTime = tools.Time2timestamp(*(v.EndTime))
			}
		} else {
			k := v.Cell
			if k >= sharemem.USER_ITEM_NORMAL {
				return config.OVERRUN
			}
			shm_user.Item.Normal[k].Id.NewVal = v.Id
			shm_user.Item.Normal[k].Id.OldVal = v.Id
			shm_user.Item.Normal[k].Type = v.Type
			shm_user.Item.Normal[k].Num = v.Num
			shm_user.Item.Normal[k].Day = v.Day
			if v.CdTime != nil {
				shm_user.Item.Normal[k].CdEndTime = tools.Time2timestamp(*(v.CdTime))
			}
			if v.EndTime != nil {
				shm_user.Item.Normal[k].EndTime = tools.Time2timestamp(*(v.EndTime))
			}
		}
	}
	return config.OK
}

func DM_user_equip(shm_user *sharemem.User) int16 {
	var data []db.DbEquip
	res := db.Conn.Where("uid = ?", shm_user.Id.NewVal).Find(&data)
	if res.Error != nil {
		return config.DBERROR
	}
	for _, v := range data {
		if v.Type == db.EquipTypeNormal {
			idx := v.Cell
			if idx >= sharemem.USER_EQUIP {
				return config.OVERRUN
			}
			shm_user.Equip[idx].Id.NewVal = v.Id
			shm_user.Equip[idx].Id.OldVal = v.Id
			shm_user.Equip[idx].Cell = int32(idx)
			shm_user.Equip[idx].Level = v.Level
			shm_user.Equip[idx].Exp = v.Exp
			shm_user.Equip[idx].LevelGroup = v.LevelGroup
			// if v.AffixList != "" {
			// 	err := json.Unmarshal([]byte(v.AffixList), &shm_user.Equip[idx].AffixList)
			// 	if err != nil {
			// 		return config.JSONERROR
			// 	}
			// }
			// if v.AffixRemakeList != "" {
			// 	err := json.Unmarshal([]byte(v.AffixRemakeList), &shm_user.Equip[idx].AffixRemakeList)
			// 	if err != nil {
			// 		return config.JSONERROR
			// 	}
			// }
			shm_user.Equip[idx].RoleId = v.RoleId
			if v.JewelList != "" {
				err := json.Unmarshal([]byte(v.JewelList), &shm_user.Equip[idx].JewelList)
				if err != nil {
					return config.JSONERROR
				}
			}
			if v.SkillList != "" {
				err := json.Unmarshal([]byte(v.SkillList), &shm_user.Equip[idx].SkillList)
				if err != nil {
					return config.JSONERROR
				}
			}
		} else if v.Type == db.EquipTypeJewel {
			idx := v.Cell
			if idx >= sharemem.USER_EQUIP_JEWEL {
				return config.OVERRUN
			}
			shm_user.EquipJewel[idx].Id.NewVal = v.Id
			shm_user.EquipJewel[idx].Id.OldVal = v.Id
			shm_user.EquipJewel[idx].Cell = int32(idx)
		}
	}
	return config.OK
}

func DM_user_team(shm_user *sharemem.User) int16 {
	var data []db.DbTeam
	res := db.Conn.Where("uid = ?", shm_user.Id.NewVal).Find(&data)
	if res.Error != nil {
		return config.DBERROR
	}
	for k, v := range data {
		if k >= sharemem.TEAM_MAX {
			return config.OVERRUN
		}
		shm_user.Team[k].Id.NewVal = v.Id
		shm_user.Team[k].Id.OldVal = v.Id
		shm_user.Team[k].SetName(v.Name)
		if v.FightRoleList != "" {
			err := json.Unmarshal([]byte(v.FightRoleList), &(shm_user.Team[k].FightRoleList))
			if err != nil {
				return config.JSONERROR
			}
		}
		if v.AssistRoleList != "" {
			err := json.Unmarshal([]byte(v.AssistRoleList), &(shm_user.Team[k].AssistRoleList))
			if err != nil {
				return config.JSONERROR
			}
		}
	}
	return config.OK
}

func DM_user_mail(user *sharemem.User) int16 {
	var data []db.DbMail
	res := db.Conn.Where("uid = ?", user.Id.NewVal).Find(&data)
	if res.Error != nil {
		return config.DBERROR
	}

	for k, v := range data {
		if k >= sharemem.MAIL_MAX {
			return config.OVERRUN
		}
		user.Mail[k].Id.NewVal = v.Id
		user.Mail[k].Id.OldVal = v.Id
		user.Mail[k].SetTitle(v.Title)
		user.Mail[k].SetContent(v.Content)
		user.Mail[k].SetSender(v.Sender)
		user.Mail[k].SendTime = v.SendTime
		user.Mail[k].ExpireTime = v.ExpireTime
		user.Mail[k].IsRead = v.IsRead
		user.Mail[k].IsAttachmentGot = v.IsAttachmentGot
		user.Mail[k].IsImportance = v.IsImportance
		if v.ItemList != "" {
			err := json.Unmarshal([]byte(v.ItemList), &(user.Mail[k].ItemList))
			if err != nil {
				return config.JSONERROR
			}
		}
	}

	return config.OK
}

func DM_user_home(user *sharemem.User) int16 {
	var data db.DbUserHome
	res := db.Conn.Where("uid = ?", user.Id.NewVal).Find(&data)
	if res.Error != nil {
		return config.DBERROR
	}
	if data.Uid != 0 {
		user.UserHome.Exp = data.Exp
		user.UserHome.Level = data.Level
		user.UserHome.Id.NewVal = data.Id
		user.UserHome.Id.OldVal = data.Id
		user.UserHome.Uid = data.Uid
	}
	return config.OK
}

func DM_user_home_building(user *sharemem.User) int16 {
	var data []db.DbUserHomeBuilding
	res := db.Conn.Where("uid = ?", user.Id.NewVal).Find(&data)
	if res.Error != nil {
		return config.DBERROR
	}
	for k, v := range data {
		if k >= sharemem.BUILDING_MAX {
			return config.OVERRUN
		}
		user.UserHome.BuildingList[k].BuildingUuid.NewVal = v.BuildingUuid
		user.UserHome.BuildingList[k].BuildingUuid.OldVal = v.BuildingUuid
		user.UserHome.BuildingList[k].BuildingId = v.BuildingId
		user.UserHome.BuildingList[k].PosX = v.PosX
		user.UserHome.BuildingList[k].PosY = v.PosY
		user.UserHome.BuildingList[k].PosZ = v.PosZ
		user.UserHome.BuildingList[k].Level = v.Level

		if len(v.Farm) != 0 {
			err := json.Unmarshal([]byte(v.Farm), &(user.UserHome.BuildingList[k].Farm))
			if err != nil {
				logger.Error("unmarshal user home_building Farm err: %v, uid: %v", err, user.GetUid())
				return config.DBERROR
			}
		}
		if len(v.Factory) != 0 {
			err := json.Unmarshal([]byte(v.Factory), &(user.UserHome.BuildingList[k].Factory))
			if err != nil {
				logger.Error("unmarshal user home_building Factory err: %v, uid: %v", err, user.GetUid())
				return config.DBERROR
			}
		}
	}
	return config.OK
}

func DM_user_data(user *sharemem.User) int16 {
	var list []db.DbUserData = nil
	err := db.Conn.Where("uid = ?", user.GetUid()).Find(&list).Error
	if err != nil {
		logger.Error("db query user data error: %v, uid: %v", err, user.GetUid())
		return config.DBERROR
	}
	if len(list) == 0 {
		logger.Error("db not exist user data, uid: %v", user.GetUid())
		return config.DBERROR
	}
	if len(list) > 1 {
		logger.Error("db exist user data dup data, uid: %v", user.GetUid())
		return config.DBERROR
	}
	userData := list[0]

	if len(userData.SceneData) != 0 {
		err = json.Unmarshal([]byte(userData.SceneData), &(user.UserScene))
		if err != nil {
			logger.Error("unmarshal user scene err: %v, uid: %v", err, user.GetUid())
			return config.DBERROR
		}
	}
	if len(userData.QuestData) != 0 {
		err = json.Unmarshal([]byte(userData.QuestData), &(user.UserQuest))
		if err != nil {
			logger.Error("unmarshal user quest err: %v, uid: %v", err, user.GetUid())
			return config.DBERROR
		}
	}
	if len(userData.ShopData) != 0 {
		err = json.Unmarshal([]byte(userData.ShopData), &(user.UserShop))
		if err != nil {
			logger.Error("unmarshal user shop err: %v, uid: %v", err, user.GetUid())
			return config.DBERROR
		}
	}
	if len(userData.GachaData) != 0 {
		err = json.Unmarshal([]byte(userData.GachaData), &(user.UserGacha))
		if err != nil {
			logger.Error("unmarshal user gacha err: %v, uid: %v", err, user.GetUid())
			return config.DBERROR
		}
	}
	if len(userData.CodexData) != 0 {
		err = json.Unmarshal([]byte(userData.CodexData), &(user.UserCodex))
		if err != nil {
			logger.Error("unmarshal user codex err: %v, uid: %v", err, user.GetUid())
			return config.DBERROR
		}
	}
	if len(userData.WeaponData) != 0 {
		err = json.Unmarshal([]byte(userData.WeaponData), &(user.UserWeapon))
		if err != nil {
			logger.Error("unmarshal user weapon err: %v, uid: %v", err, user.GetUid())
			return config.DBERROR
		}
	}
	if len(userData.ActivityData) != 0 {
		err = json.Unmarshal([]byte(userData.ActivityData), &(user.UserActivity))
		if err != nil {
			logger.Error("unmarshal user activity err: %v, uid: %v", err, user.GetUid())
			return config.DBERROR
		}
	}

	user.SceneId = userData.SceneId
	user.TeamId = userData.TeamId
	user.SetClientData(userData.ClientData)
	user.CurrMailId = userData.CurrMailId
	user.GlobalMailId = userData.GlobalMailId
	user.TimerMailId = userData.TimerMailId
	user.UserActivity.TowerArea = userData.TowerArea
	user.UserActivity.TowerLevel = userData.TowerLevel
	user.UserActivity.TowerPassArea = userData.TowerPassArea
	user.UserActivity.TowerPassLevel = userData.TowerPassLevel
	user.UserActivity.TowerPassTime = userData.TowerPassTime

	return config.OK
}

func DM_user(shm_user *sharemem.User, user *db.DbUser) int16 {
	if shm_user.Id.NewVal != user.Id {
		return config.FAIL
	}
	var res int16
	// 载入user_role
	res = DM_user_role(shm_user)
	if res != config.OK {
		return res
	}
	// 载入user_item
	res = DM_user_item(shm_user)
	if res != config.OK {
		return res
	}
	// 载入user_equip
	res = DM_user_equip(shm_user)
	if res != config.OK {
		return res
	}
	// 载入user_team
	res = DM_user_team(shm_user)
	if res != config.OK {
		return res
	}
	// 载入user_mail
	res = DM_user_mail(shm_user)
	if res != config.OK {
		return res
	}
	// 载入user_home
	res = DM_user_home(shm_user)
	if res != config.OK {
		return res
	}
	//载入user_home_building
	res = DM_user_home_building(shm_user)
	if res != config.OK {
		return res
	}

	// 载入user_data
	res = DM_user_data(shm_user)
	if res != config.OK {
		return res
	}

	// 最后处理user表
	shm_user.Id.OldVal = user.Id
	shm_user.SetName(user.Name)
	shm_user.Gold = user.Gold
	shm_user.Gem.NewVal = user.Gem
	shm_user.Gem.OldVal = user.Gem
	shm_user.Level = user.Level
	shm_user.Exp = user.Exp
	if user.Created != nil {
		shm_user.Created = tools.Time2timestamp(*(user.Created))
	}
	if user.Updated != nil {
		shm_user.LastOfflineTime = tools.Time2timestamp(*(user.Updated))
	}
	return config.OK
}
